import * as THREE from "three";
import { RefObject } from "react";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { ValueType } from "rc-input-number";
import { Axis } from "./constant";
import { OBJLoader } from "three/addons/loaders/OBJLoader.js";
// import monkey from "@/model/monkey.obj";
// import monkey from "../model/monkey.obj";

// public variables
let canvas: HTMLCanvasElement;
let renderer: THREE.WebGLRenderer;
let controls: OrbitControls;
let scene: THREE.Scene;
let camera: THREE.PerspectiveCamera;
let light: THREE.Light;
let instance: THREE.Mesh | THREE.Object3D;
let boxHelper: THREE.BoxHelper;
let raycaster: THREE.Raycaster;
let currentColor: string = "#ffffff";

const initScene = (canvasRef: RefObject<HTMLCanvasElement>) => {
  if (!canvasRef.current) return;
  canvas = canvasRef.current;
  // WebGLRenderer参数可以指定canvas
  renderer = new THREE.WebGLRenderer({ canvas, antialias: true });

  // 场景中要素的出实话
  initSceneBgc();
  initCamera();
  initLight();
  initControls();

  // // 声明物体的几何和材质信息
  // const geometry = new THREE.BoxGeometry();
  // const material = new THREE.MeshBasicMaterial({ color: 0x7f7f7f });
  // // 根据几何和材质生产Mesh
  // instance = new THREE.Mesh(geometry, material);

  // const path = '/src/model/monkey.obj'
  const path = '../model/monkey.obj'

  modelLoader(path);

  const animate = () => {
    // 实时更新包围盒update
    if (boxHelper) {
      boxHelper.update();
    }
    requestAnimationFrame(animate);
    renderer.setSize(canvas.clientWidth, canvas.clientHeight);
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
    controls.update();
    renderer.render(scene, camera);
  };
  animate();
};

// 初始化场景&颜色
const initSceneBgc = () => {
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x000000);
}

// 初始化相机
const initCamera = () => {
  camera = new THREE.PerspectiveCamera(
    75,
    canvas.clientWidth / canvas.clientHeight,
    0.1,
    1000
  );
  camera.position.set(4, 4, 4);
}

// 初始化灯光
const initLight = () => {
  light = new THREE.PointLight(0xffffff, 666);
  light.position.set(10, 10, 10);
  scene.add(light);
}

// 初始化控制器
const initControls = () => {
  controls = new OrbitControls(camera, renderer.domElement);
  controls.update();
}

// 载入模型 only obj
const modelLoader = (urlObj: string) => {
  const loader = new OBJLoader();
  loader.load(
    urlObj,
    function (object) {
      console.log('加载了一次');
      if (instance) return;
      instance = object;
      initBoundingBox(instance);
      scene.add(instance);
    },
    function (progress) {
      console.log((progress.loaded / progress.total) * 100 + "% loaded");
    },
    function (error) {
      console.log("An error happened", error);
    }
  );
};

// 初始化轴线
const initAxesHelper = (length: number) => {
  const axesHelper = new THREE.AxesHelper(length);
  scene.add(axesHelper);
};

// 初始化某个mesh的包围盒
const initBoundingBox = async (mesh: THREE.Mesh | THREE.Object3D, update = true) => {
  const box = new THREE.Box3().setFromObject(mesh);
  // 获取物体的长宽高
  const width = box.max.x - box.min.x;
  const height = box.max.y - box.min.y;
  const depth = box.max.z - box.min.z;
  const meanSize = (width + height + depth) / 3;
  initAxesHelper(meanSize * 3);
  boxHelper = new THREE.BoxHelper(mesh, 0xffffff);
  if (!update) return;
  scene.add(boxHelper);
};

// 点击canvas场景 获得点击的目标
const clickRender = (pointer: THREE.Vector2) => {
  raycaster = new THREE.Raycaster();
  raycaster.setFromCamera(pointer, camera);
  // 计算物体和射线的焦点
  const intersects = raycaster.intersectObjects(scene.children);
  if (!intersects.length) return;
  for (let i = 0; i < intersects.length; i++) {
    // if (!intersects[i].object || intersects[i].object.type === 'AxesHelper' || intersects[i].object.type === 'BoxHelper') return;
    // 只针对mesh进行操作
    if (intersects[i].object.type === "Mesh") {
      console.log(intersects[i].object);
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (intersects[i].object as any).material.color.set(currentColor);
    }
  }
  renderer.render(scene, camera);
};

// 处理物体旋转
const rotateChange = (degree: ValueType | null, axis: Axis) => {
  if (!instance) return;
  switch (axis) {
    case Axis.x:
      instance.rotation.x = THREE.MathUtils.degToRad(degree as number);
      break;
    case Axis.y:
      instance.rotation.y = THREE.MathUtils.degToRad(degree as number);
      break;
    case Axis.z:
      instance.rotation.z = THREE.MathUtils.degToRad(degree as number);
      break;
  }
};

// 处理物体缩放
const scaleChange = (value: ValueType | null, axis: Axis) => {
  switch (axis) {
    case Axis.x:
      instance.scale.x = (value as number) / 100;
      break;
    case Axis.y:
      instance.scale.y = (value as number) / 100;
      break;
    case Axis.z:
      instance.scale.z = (value as number) / 100;
      break;
  }
};

// 处理物体位移
const positionChange = (value: ValueType | null, axis: Axis) => {
  switch (axis) {
    case Axis.x:
      instance.position.x = (value as number) / 100;
      break;
    case Axis.y:
      instance.position.y = (value as number) / 100;
      break;
    case Axis.z:
      instance.position.z = (value as number) / 100;
      break;
  }
};

// 重制模型 transform
const resetModel = () => {
  instance.scale.x = 1;
  instance.scale.y = 1;
  instance.scale.z = 1;
  instance.rotation.x = 0;
  instance.rotation.y = 0;
  instance.rotation.z = 0;
  instance.position.x = 0;
  instance.position.y = 0;
  instance.position.z = 0;
  // instance.material.color.set(0x7f7f7f);
};

// 设置物体颜色
const setColor = (value: string) => {
  currentColor = value;
};

// 重置相机 
const resetCamera = () => {
  camera.position.set(4, 4, 4);
};

export {
  initScene,
  rotateChange,
  scaleChange,
  positionChange,
  resetModel,
  clickRender,
  setColor,
  resetCamera,
};
